package com.radiosamhan.ryoko;

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.LinkedList;
import java.util.Queue;

import com.radiosamhan.ryoko.R;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.TextView;

public class RyokoActivity extends Activity {

	private Thread _server = null;
	final Handler _handler = new Handler();
	Queue<String> _inputs = new LinkedList<String>();
	private String _hardwareIp = "192.168.0.1";
	private Integer _hardwarePort = 80;
	private TelnetClient _telnetClient = new TelnetClient();

	private class Listener extends Thread {

		private DatagramSocket _socket = null;
		private DatagramPacket _packet = null;
		private byte[] _buffer = new byte[1024];
		private Boolean _stopped = false;

		public void interrupt() {
			super.interrupt();
			_stopped = true;
			Log.d("UDP", "UDP server stopped.");
			_socket.close();
		}

		public void run() {
			Log.d("UDP", "Running UDP Server at port 6667...");
			try {
				_socket = new DatagramSocket(6667);
			} catch (SocketException e) {
				Log.d("UDP", "Error creating DatagramSocket.");
			}
			_packet = new DatagramPacket(_buffer, _buffer.length);
			Log.d("UDP", "Receiving UDP packet...");
			try {
				while (!_stopped) {
					_socket.receive(_packet);
					String data = new String(_packet.getData());
					data = data.substring(0, _packet.getLength());
					Log.d("UDP", "Received UDP packet: " + data);
					_inputs.add(data);
					_handler.post(_updatingUi);
				}
			} catch (InterruptedIOException e) {
				Thread.currentThread().interrupt();
				Log.d("UDP", "Interupted IO Exception.");
			} catch (IOException e) {
				if (!_stopped) {
					Log.d("UDP", "Error receiving DatagramPacket.");
				}
			}
		}
	}

	private class Shouter extends Thread {
		public void run() {
			// For the first run, maybe the connection is not ready yet because
			// sometimes the data is not complete.
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
			}
			Log.d("UDP", "Start shouting...");
			_send("ATS 0101");
			_send("ATS 0102");
			_send("ATS 0103");
			_send("ATS 0104");
			_send("ATS 0105");
			_send("ATS 0106");
			_send("ATS 0107");
			Log.d("UDP", "Shouting end");
		}
	}

	final Runnable _updatingUi = new Runnable() {
		public void run() {
			_updateUi();
		}
	};

	private void _updateUi() {
		TextView text = null;
		String data = "";
		String hc = "";
		int value = 0;
		while (!_inputs.isEmpty()) {
			data = _inputs.poll();
			Log.d("data", data);
			hc = data.substring(0, 4);
			if (hc.equals("0101")) {
				text = (TextView) findViewById(R.id.swr);
			} else if (hc.equals("0102")) {
				text = (TextView) findViewById(R.id.power_w);
			} else if (hc.equals("0103")) {
				text = (TextView) findViewById(R.id.ipa);
			} else if (hc.equals("0104")) {
				text = (TextView) findViewById(R.id.pdm_t);
			} else if (hc.equals("0105")) {
				text = (TextView) findViewById(R.id.pa_t);
			} else if (hc.equals("0106")) {
				text = (TextView) findViewById(R.id.pdm_v);
			} else if (hc.equals("0107")) {
				text = (TextView) findViewById(R.id.pa_v);
			} else {
				continue;
			}
			hc = data.substring(4, 7);
			Log.d("data", hc);
			value = Integer.parseInt(hc);
			text.setText(Integer.toString(value));
		}
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		_bindRefresh();
		_bindPowerOff();
		_bindPowerOn();
		_bindPowerLevelDown();
		_bindPowerLevelUp();
		_bindModulationLevelDown();
		_bindModulationLevelUp();
	}

	@Override
	protected void onResume() {
		super.onResume();
		_server = new Listener();
		_server.start();
		Thread shouter = new Shouter();
		shouter.start();
		_readSettings();
	}

	@Override
	protected void onPause() {
		super.onPause();
		_server.interrupt();
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		getMenuInflater().inflate(R.menu.options, menu);
		menu.findItem(R.id.settings).setIntent(
				new Intent(this, SettingsActivity.class));
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		String menu = item.getTitle().toString();
		if (menu.equals(getString(R.string.settings))) {
			super.onOptionsItemSelected(item);
			startActivity(item.getIntent());
		}
		return true;
	}

	private void _bindRefresh() {
		View view = (View) findViewById(R.id.refresh);
		view.setOnClickListener(new OnClickListener() {
			public void onClick(View view) {
				_sendTcp("ATS");
			}
		});
	}

	private void _bindPowerOn() {
		View view = (View) findViewById(R.id.power_on);
		view.setOnClickListener(new OnClickListener() {
			public void onClick(View view) {
				_send("ATP 0110100");
				_sendTcp("ATP 0110100");
			}
		});
	}

	private void _bindPowerOff() {
		View view = (View) findViewById(R.id.power_off);
		view.setOnClickListener(new OnClickListener() {
			public void onClick(View view) {
				_send("ATP 0110000");
				_sendTcp("ATP 0110000");
			}
		});
	}

	private void _bindPowerLevelUp() {
		View view = (View) findViewById(R.id.power_l_up);
		view.setOnClickListener(new OnClickListener() {
			public void onClick(View view) {
				_send("ATP 0111100");
				_sendTcp("ATP 0111100");
			}
		});
	}

	private void _bindPowerLevelDown() {
		View view = (View) findViewById(R.id.power_l_down);
		view.setOnClickListener(new OnClickListener() {
			public void onClick(View view) {
				_send("ATP 0111000");
				_sendTcp("ATP 0111000");
			}
		});
	}

	private void _bindModulationLevelUp() {
		View view = (View) findViewById(R.id.modulation_l_up);
		view.setOnClickListener(new OnClickListener() {
			public void onClick(View view) {
				_send("ATP 0112100");
				_sendTcp("ATP 0112100");
			}
		});
	}

	private void _bindModulationLevelDown() {
		View view = (View) findViewById(R.id.modulation_l_down);
		view.setOnClickListener(new OnClickListener() {
			public void onClick(View view) {
				_send("ATP 0112000");
				_sendTcp("ATP 0112000");
			}
		});
	}

	private void _readSettings() {
		SharedPreferences pref = getSharedPreferences(
				SettingsActivity.SETTINGS, Context.MODE_PRIVATE);
		if (pref.contains(SettingsActivity.HARDWARE_IP)) {
			_hardwareIp = pref.getString(SettingsActivity.HARDWARE_IP,
					"192.168.0.1");
		} else {
			_hardwareIp = "192.168.0.1";
		}
		if (pref.contains(SettingsActivity.HARDWARE_PORT)) {
			_hardwarePort = pref.getInt(SettingsActivity.HARDWARE_PORT, 80);
		} else {
			_hardwarePort = 80;
		}
	}

	private void _send(String message) {
		Log.d("Send", "Sending UDP Message...");
		DatagramSocket socket;
		InetAddress address;
		DatagramPacket packet;
		byte[] data;

		try {
			socket = new DatagramSocket();
		} catch (SocketException e) {
			Log.d("Send", "Error creating DatagramSocket.");
			return;
		}
		try {
			address = InetAddress.getByName(_hardwareIp);
		} catch (UnknownHostException e) {
			Log.d("Send", "Error creating InetAddress.");
			return;
		}
		data = new byte[1024];
		data = message.getBytes();
		packet = new DatagramPacket(data, data.length, address, 6667);
		try {
			socket.send(packet);
		} catch (IOException e) {
			Log.d("Send", "Error sending packet.");
			return;
		}
		socket.close();
	}
	
	private void _sendTcp(String message) {
		try {
			_telnetClient.connect(_hardwareIp, _hardwarePort);
		} catch (IOException e) {
			return;
		}
		String result = _telnetClient.attention(message);
		_telnetClient.disconnect();
		if (result.length() > 0) {
			String[] list = result.split(",");
			for (int i = 0; i < list.length; i++) {
				_inputs.add(list[i].trim());
			}
			_updateUi();
		}
	}

}